(https://www.pinterest.com/pin/492722015457646968/)
在 git、npm 成為主流後,為了能獨立各自的開發環境,我們會為每個專案建立一個 repository 進行版控和套件管理,這種方式就稱為 Multi-Repo。
不過產品線的範圍變大時,專案 B、C 都是基於專案 A 的底層程式去做新服務的開發,或甚至專案之間都有一些相依的程式碼時,除非能將這些共用的程式另外做成套件,並且保證每次的更動在多個專案下都能運作,不然通常會很難維護在同一支產品線下的各個專案。
跟 Multi-Repo 相反,Mono-Repo是將相關的產品專案都放在同一個 repository。
Mono-Repo 的好處主要有:
不過有幾個問題是:
目前對於Mono-Repo的管理功能最完整的工具是Lerna,在一些著名的大型專案,像是Babel、React、Storybook等都能看到它被大量使用,可見這也成為程式碼管理的主流方式之一。
npm i -g lerna
- 全域安裝lernalerna init
- 專案初始化,建立package.json、lerna.json和packages目錄lerna create <pkg-name>
- 建立package目錄,並產生package.json、README.md和預設目錄lerna ls
: 列出所有packages。
-a
- 可列出所有設為private的packages--dev
- 將依賴安裝到devDendency--peer
- 將依賴安裝到peerDendencylerna add <external-pkg-name>
- 為所有packages安裝外部依賴lerna add <internal-pkg-name>
- 為所有packages(除依賴本身以外)安裝內部依賴lerna add <internal-pkg-name> --scope=<target-pkg-name>
- 在目標package安裝內部依賴lerna add <internal-pkg-name> <worksapce-name>/<prefix->*
- 將內部依賴安裝到所有適配的packageslerna bootstrap
- 安裝package所需要的依賴,如果內部package互相依賴則自動安裝。
--hoist
- 將同版本的同套件,安裝到根目錄下的node_modules下lerna clean
- 移除所有package底下的node_moduleslerna run <command>
- 在所有packages下執行npm指令lerna exec 'command'
- 在所有packages下執行shell指令lerna version [major | minor | patch | premajor | preminor | prepatch | prerelease]
- 跳版本lerna publish
- 發布packageslerna changed
- 找出跟上次發布有差異的packagespackages
: workspaces的列表version
: 預設fixed mode。如果要設成independent mode,則改為 "independent"
npmClient
: 套件管理的執行指令,預設為npm。如果專案是以yarn執行,則改為"yarn"
command
publish
ignoreChanges
: 忽略變更的檔案列表,例如.gitignore、README.md等。避免不必要的更新message
: 執行lerna version
提交commit時的內容文字registry
: npm server的位置。預計為 npmjs.org以執行測試job為例,在CI上希望只針對有修改的packages執行測試。相關的lerna指令可以這樣寫 -
# 列出所有從release_tag之後有修改過的packages
lerna ls --all --since <release_tag>
# 在這些packages安裝依賴,並把相同套件安裝在根目錄的node_modules
lerna bootstrap --hoist --since <release_tag>
# 在這些packages執行測試的npm指令
lerna run test --since <release_tag> --parallel
在一開始嘗試以lerna管理mono repo時,發現到有些麻煩的地方,像是安裝全域依賴時,會希望依賴可以直接安裝在根目錄的node_modules下,讓所有的packages都能以link方式引用依賴。在lerna中你可能要這樣做以下三件事情 -
lerna add <pkg-name>
lerna bootstrap --hoist
lerna clean
過不久後我改用了yarn的workspaces,以上面的安裝依賴為例,我只要輸入 yarn add -W <pkg-name>
,就能達到那3個lerna指令才能做到的事,相當的簡潔快速。
不過聽完這個議程之後,我發現這兩個工具是可以相輔相成的。因為在某些狀況下,使用Lerna還是比較理想的。
簡單、單一範圍的事情交給yarn workspaces;而複雜、大範圍的事情就給Lerna。個人覺得這樣的搭配是最適合管理mono repo,在google相關文章時會發現有些大大也是這樣建議使用。